local text = {}
local config = require "config"

function text:new(object)
    object = object or {}
    self.__index = self
    setmetatable(object, self)
    return object
end

function text:add_char(line_num, ch, pos)
    if pos == nil then
        self[line_num] = (self[line_num] == nil) and ch or (self[line_num] .. ch)
    else
        self[line_num] = (self[line_num] == nil) and ch
            or (string.sub(self[line_num], 1, pos - 1) .. ch .. string.sub(self[line_num], pos))
    end
end

function text:remove_char(line_num, pos)
    if pos == 1 then
        self:append_line(line_num)
    else
        self[line_num] = string.sub(self[line_num], 1, pos - 2) .. string.sub(self[line_num], pos)
    end
end

function text:new_line(line_num, pos)
    if pos == (#self[line_num] + 1) then
        table.insert(self, line_num + 1, "")
    else
        local append_line = string.sub(self[line_num], pos) or ""
        self[line_num] = string.sub(self[line_num], 1, pos - 1) or ""
        table.insert(self, line_num + 1, append_line)
    end
end

-- merge text[line_num] to text[line_num - 1]
function text:append_line(line_num)
    if line_num > 1 and line_num <= #self then
        self[line_num - 1] = self[line_num - 1] .. self[line_num]
        table.remove(self, line_num)
    end
end

-- write text[line_num] (w_start, w_end) to file
function text:write_line(file, line_num, w_start)
    local line = self[line_num]
    line = string.sub(line, w_start)
    file:write(line .. "\r\n")
end

function text:write_lines(file, line_num, w_start, win_rows)
    local write_rows = (#self > win_rows) and win_rows or #self
    for i = line_num, (line_num + write_rows - 1) do
        self:write_line(file, i, w_start)
    end
end

function text:save(filename)
    local file = assert(io.open(filename, "w"))
    for i = 1, #self do
        if string.sub(self[i], -1) == "\n" then
            file:write(self[i])
        else
            file:write(self[i] .. "\n")
        end
    end
end

function text:load(filename)
    local whitespaces = string.rep(" ", config.tabsize)
    for line in io.lines(filename) do
        line = string.gsub(line, "\t", whitespaces)
        line = string.gsub(line, "\r", "")
        line = string.gsub(line, "\n", "")
        self[#self + 1] = line
    end
    config.filename = filename
end

return text